package com.one.group.user.service.impl;

import cn.dev33.satoken.stp.StpUtil;

import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import com.mybatisflex.core.tenant.TenantManager;
import com.one.group.enums.ErrorCode;
import com.one.group.enums.ResultEnum;
import com.one.group.model.dto.*;
import com.one.group.model.entity.SpCell;
import com.one.group.model.entity.UserAccount;
import com.one.group.result.Result;
import com.one.group.service.SpCellService;
import com.one.group.service.UserAccountService;
import com.one.group.user.service.UserService;
import com.one.group.user.tool.MqMassageTool;
import com.one.group.utils.ResultUtil;
import com.one.group.utils.ThrowUtil;
import org.apache.dubbo.config.annotation.DubboReference;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.Random;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private RedisTemplate redisTemplate;
    @DubboReference
    private UserAccountService userAccountService;
    @Override
    public String login(UserLoginDto userloginDto) {
        UserAccount userAccount = userAccountService.mySelectOneByQuery(userloginDto);
        ThrowUtil.throwIf(userAccount == null, ResultEnum.USERNAME_OR_PASSWORD_ERROR);
        //2.获取盐
        String salt = userAccount.getSalt();
        //3.再次进行加密
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        String md5Password = md5.digestHex(userloginDto.getPassword() + salt);
        //4.使用加密后的密码和服务器存储的加密密码进行对比，如果一致就ok
        ThrowUtil.throwIf(!userAccount.getPassword().equals(md5Password), ResultEnum.USERNAME_OR_PASSWORD_ERROR);
        StpUtil.login(userAccount.getId(), new SaLoginParameter()
                .setExtra("tenant_id", userAccount.getTenantId()
                ));
        return StpUtil.getTokenValue();
    }
    @Autowired
    private MqMassageTool mqMassageTool;
    @Override
    public Result sendCode(SendCodeDto sendCodeDto) {
        //1.生成验证码
        Integer code = Integer.valueOf(RandomUtil.randomNumbers(6));
        //将验证码保存到redis中，5分钟有效
        redisTemplate.opsForValue().set("code:" + sendCodeDto.getEmail(), code);
        redisTemplate.expire("code:" + sendCodeDto.getEmail(), Duration.ofMinutes(5));
        //编写发送邮件消息
        SpSendEmailDto spSendEmailDto = new SpSendEmailDto();
        spSendEmailDto.setEmail(sendCodeDto.getEmail());
        //编写邮件内容
        String message = "<h2>智慧物业平台</h2>\n"
                + "<p>尊敬的用户您好：</p>\n"
                + "<p>您本次的验证码为：<strong>" + code + "</strong></p>"
                + "<p>验证码有效期为5分钟，请及时使用。</p>"
                + "<p>如非本人操作，请忽略此邮件。</p>";
        spSendEmailDto.setContent(message);
        mqMassageTool.send(spSendEmailDto);
        return ResultUtil.success();
    }
    @DubboReference
    private SpCellService spCellService;
    @Override
    public Result register(RegisterDto registerDto) {
        if(!verifyCode(registerDto.getEmail(), registerDto.getCode())){
            return ResultUtil.error(ErrorCode.Code_NOT_EXIST);
        }
        //配置忽略多租户
        TenantManager.ignoreTenantCondition();
        //获取小区信息
        SpCell spCell =spCellService.getById(registerDto.getCellId());
        //构建账号
        UserAccount userAccount = new UserAccount();
        userAccount.setPhone(registerDto.getPhone());
        userAccount.setRealName(registerDto.getRealName());
        userAccount.setUsername(registerDto.getUsername());
        userAccount.setEmail(registerDto.getEmail());
        userAccount.setCellId(registerDto.getCellId());
        //设置盐
        String salt = RandomUtil.randomString(16);
        userAccount.setSalt(salt);
        //设置手机后六位密码
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        String md5Password = md5.digestHex(registerDto.getPhone().substring(5) + salt);
        userAccount.setPassword(md5Password);
        userAccount.setTenantId(spCell.getTenantId());
        userAccount.setRealName(registerDto.getRealName());
        userAccount.setStatus(0);
        userAccountService.save(userAccount);
        return ResultUtil.success();
    }

    @Override
    public Boolean verifyCode(String email,String code) {
        Integer code1 = (Integer) redisTemplate.opsForValue().get("code:" + email);
        if (code1 != null) {
            return code1.equals(Integer.valueOf(code));
        }else return false;
    }
}
